package com.cloud.example.business.async.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloud.async.business.body.BusinessResult;
import com.cloud.async.business.context.support.StandardAsyncContext;
import com.cloud.async.result.core.body.ResultBody;
import com.cloud.example.business.async.entity.Car;
import com.cloud.example.business.async.entity.Person;
import com.cloud.example.business.async.service.AsyncService;
import com.cloud.example.business.async.service.CalledAsyncService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author chengrui
 */
@Service
public class AsyncServiceImpl implements AsyncService {
    /**
     * logger
     */
    private final Log logger = LogFactory.getLog(getClass());

    @Autowired
    CalledAsyncService calledAsyncService;

    @Autowired
    StandardAsyncContext standardAsyncContext;

    @Override
    public String testAsync() {
        String name = "";

        long startTime = System.currentTimeMillis();

        //涉及相应调用（模拟调用且有3s时间等待业务操作）
        //本身实现等同于example1() 方法见下
        BusinessResult taskId1 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsync(name), String.class);
        BusinessResult taskId2 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsync(name), String.class);
        BusinessResult taskId3 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsync(name), String.class);
        BusinessResult taskId4 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsync(name), String.class);


        BusinessResult taskId5 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsyncObj(name), Person.class);
        BusinessResult taskId6 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsyncObj(name), Person.class);
        BusinessResult taskId7 = standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsyncObj(name), Person.class);
        BusinessResult taskId8= standardAsyncContext.doBusiness(() -> calledAsyncService.calledAsyncObj(name), Person.class);

        try {
            //假设执行业务
            TimeUnit.SECONDS.sleep(4);
        } catch (Exception e) {

        }

        ResultBody<String> result1 = standardAsyncContext.result().getResult(taskId1.getSuccessTaskId(), String.class);
        logger.info("result1:[{}]" + result1);

        ResultBody<String> result2 = standardAsyncContext.result().getResult(taskId2.getSuccessTaskId(), 3000L, String.class);
        logger.info("result2:[{}]" + result2);

        ResultBody<Person> result3 = standardAsyncContext.result().getResult(taskId3.getSuccessTaskId(), String.class, (str) -> {
            return JSONObject.parseObject(str, Person.class);
        });
        logger.info("result3:[{}]" + result3);

        ResultBody<Person> result4 = standardAsyncContext.result().getResult(taskId4.getSuccessTaskId(), 3000L, String.class, (str) -> {
            return JSONObject.parseObject(str, Person.class);
        });
        logger.info("result4:[{}]" + result4);


        ResultBody<Person> result5 = standardAsyncContext.result().getResult(taskId5.getSuccessTaskId(), Person.class);
        logger.info("result5:[{}]" + result5.isSuccess());
        logger.info("result5:[{}]" + result5);
        logger.info("result5:[{}]" + result5.getResult());

        ResultBody<Person>  result6 = standardAsyncContext.result().getResult(taskId6.getSuccessTaskId(), 3000L, Person.class);
        logger.info("result6:[{}]" + result6.isSuccess());
        logger.info("result6:[{}]" + result6);
        logger.info("result6:[{}]" + result6.getResult());

        ResultBody<String> result7 = standardAsyncContext.result().getResult(taskId7.getSuccessTaskId(), Person.class, JSONObject::toJSONString);
        logger.info("result7:[{}]" + result7.isSuccess());
        logger.info("result7:[{}]" + result7);
        logger.info("result7:[{}]" + result7.getResult());

        ResultBody<Person>  result8 = standardAsyncContext.result().getResult(taskId8.getSuccessTaskId(), 3000L, Person.class, (person) -> {
            person.setName("chengrui 2025-07-27-test");
            return person;
        });
        logger.info("result8:[{}]" + result8.isSuccess());
        logger.info("result8:[{}]" + result8);
        logger.info("result8:[{}]" + result8.getResult());


        long endTime = System.currentTimeMillis();

        logger.info("Time elapsed:" + ((double)endTime - (double)startTime)/1000 + "s.");

        return JSON.toJSONString(new Object());
    }


    public void example1() throws ExecutionException, InterruptedException {
        CompletableFuture<String> f = CompletableFuture.supplyAsync(()->
             calledAsyncService.calledAsync("name")
        );

        CompletableFuture<String> exceptionally = f.whenComplete((t, u) -> {
            //do something
        }).exceptionally((e) -> "");

        String s = f.get();
    }

}
